package tallinn;

import java.util.ArrayList;
import java.util.Vector;

import meshToSolid.Selector;

import processing.core.PApplet;
import simpleGeom.AbstractFace;
import simpleGeom.BasicMesh;
import simpleGeom.Bounds3D;
import simpleGeom.Box3D;
import simpleGeom.Face3D;
import simpleGeom.HasPos3D;
import simpleGeom.Mesh;
import simpleGeom.MeshFace;
import simpleGeom.Node;
import simpleGeom.Plane;
import simpleGeom.SimpleTriangle;
import simpleGeom.TriangleMath;
import simpleGeom.Vec3D;

public class BooleanMeshApplet extends PApplet {
	String folderPath = "/Users/caad/Desktop/Archive/excerpt/";
	// String inputPath=folderPath+"grottoVolume.obj";
	String inputPath = folderPath
			+ "testPiece6.objH0.4_0.13_0.1_0.24inside0.15res005.objSel.obj";

	String outputPath = inputPath + "Sel.obj";
	Bounds3D b3d;
	Face3D maxX;
	BasicMesh mesh;
	BasicMesh tube;
	String in;
	String in2;
	String out;

	public void clipPlane(){
		 Mesh mesh=new Mesh(in);
		 Plane plane=new Plane(new Vec3D(0,0,0.01f),new Vec3D(0,0,-1));
		 mesh= plane.cutMesh(mesh);
		 mesh.saveMesh(out);
	}
	public void setup() {
		size(1600, 900, P3D);
		//clipPlane();
		mesh = new BasicMesh();
		 mesh.load(in);
		 
		float d = 0.07f;
		float px=0.3f;
		float py=0.25f;
		BasicMesh tube1 = getTube(px, py, -1, px + d, py + d, 1);
		 px=0.3f;
		 py=-0.25f;
		 BasicMesh tube2 = getTube(px, py, -1, px + d, py + d, 1);
		 BasicMesh clipMesh=new BasicMesh();
		 clipMesh.load(in2);
		 /*tube.nodes.addAll(tube1.nodes);
		 tube.faces.addAll(tube1.faces);
		 tube.nodes.addAll(tube2.nodes);
		 tube.faces.addAll(tube2.faces);*/
		
		ArrayList<AbstractFace>tris=intersect(mesh,clipMesh.faces);
		mesh.faces=tris;
		mesh.saveObj(out);
	}

	public BasicMesh getTube(float x1, float y1, float z1, float x2, float y2,
			float z2) {
		BasicMesh mesh = new BasicMesh();

		Vector<Node> nodesLeft = new Vector<Node>();
		nodesLeft.add(new Node(x1, y1, z1));
		nodesLeft.add(new Node(x2, y1, z1));
		nodesLeft.add(new Node(x2, y2, z1));
		nodesLeft.add(new Node(x1, y2, z1));

		Vector<Node> nodesRight = new Vector<Node>();
		nodesRight.add(new Node(x1, y1, z2));
		nodesRight.add(new Node(x2, y1, z2));
		nodesRight.add(new Node(x2, y2, z2));
		nodesRight.add(new Node(x1, y2, z2));

		for (int i = 0; i < nodesLeft.size(); i++) {
			Node n1 = nodesLeft.get(i);
			Node n2 = nodesLeft.get((i + 1) % 4);
			Node b1 = nodesRight.get(i);
			Node b2 = nodesRight.get((i + 1) % 4);
			SimpleTriangle sT1 = new SimpleTriangle(n1, n2, b1);
			SimpleTriangle sT2 = new SimpleTriangle(b2, b1, n2);
			mesh.faces.add(sT1);
			mesh.faces.add(sT2);
		}

		mesh.nodes.addAll(nodesLeft);
		mesh.nodes.addAll(nodesRight);
	
		return mesh;
	}
	//b3d.getOffset();
	//Vector<Face3D>selectedFaces=selector.selectFaces(selector.faces, b3d, maxX, true);
	
	public void draw() {
		background(0);
		
		lights();

		scale(100);
		fill(255);
		noStroke();
		
		tube.display3D(g);
		//mesh.display3D(g);
		for (int i=0;i<mesh.faces.size();i+=20){
			AbstractFace tri=mesh.faces.get(i);
			tri.display3D(g);
		}
	}

	public ArrayList<AbstractFace> intersect(BasicMesh mesh,
			ArrayList<AbstractFace> triangles) {
		ArrayList<AbstractFace> tris = new ArrayList<AbstractFace>(triangles);
		for (int i = 0; i < tris.size(); i++) {
			SimpleTriangle tri = (SimpleTriangle) tris.get(i);
			tri.setId(0);
		}
		for (int j = 0; j < mesh.faces.size(); j++) {
			if (j % 1000 == 0)
				println("j" + j + "/" + mesh.faces.size());
			SimpleTriangle face = (SimpleTriangle) mesh.faces.get(j);
			Box3D b3d = face.getBounds3D();
			Bounds3D b3d2 = new Bounds3D();
			b3d2.offset(0.1f);
			for (int i = 0; i < tris.size(); i++) {
				SimpleTriangle tri = (SimpleTriangle) tris.get(i);

				if (tri.getId() == 0) {
					b3d2.reset();
					b3d2.addPoint(tri.getNode(0));
					b3d2.addPoint(tri.getNode(1));
					b3d2.addPoint(tri.getNode(2));
					b3d2.offset(0.1f);
					if (b3d.isOverlap(b3d2)) {
						TriangleMath math = new TriangleMath();
						Vector<SimpleTriangle> cSplits = math
								.intersectTriPlane(tri.getNode(0),
										tri.getNode(1), tri.getNode(2),
										face.getNode(0), face.getNode(1),
										face.getNode(2));
						tris.addAll(cSplits);
						if (cSplits.size() > 0) {
							tri.setId(10000);
							//println("splitted");
						}
					}
				}
			}
		}
		ArrayList<AbstractFace> finaltris = new ArrayList<AbstractFace>();
		Bounds3D b3d=mesh.getBounds3D();
		b3d.y2-=0.1f;
		for (int i = 0; i < tris.size(); i++) {
			if (i%100==0)println("i"+i+"/"+ tris.size());
			SimpleTriangle tri = (SimpleTriangle) tris.get(i);
			
			
			if (tri.getId() == 0) {
				HasPos3D center = tri.getGravityCenter();
				/*if (b3d.contains(center.getX(), center.getY(),
						center.getZ())){
					finaltris.add(tri);
				}*/
				if (!BasicMesh.contains(center.getX(), center.getY(),
						center.getZ(), 0, 1, 0, mesh.faces)) {
					finaltris.add(tri);
				}
			}
		}
		println("finaltris: "+finaltris.size());
		return finaltris;
	}
}
